OpenCode Sub Agent — 子代理委托与并行工作

Sub Agent(子代理)是 OpenCode 的工作委托(Delegation)机制, 允许 Primary Agent 将特定任务分派给专门的子代理独立执行,实现并行工作、关注点分离和权限隔离。 这是 OpenCode Agent 体系区别于传统单线程 AI 编程助手的核心能力之一。

1. 概述

1.1 什么是 Sub Agent

Sub Agent 是一种 mode 为 "subagent" 的 Agent 实例, 不能由用户直接交互(不可通过 Tab 切换), 而是由 Primary Agent 在 ReAct 循环中通过 task 工具调度执行, 或由用户通过 @agent-name 手动调用。

核心本质:Sub Agent = 一个独立的 ReAct 循环 + 专属 System Prompt + 受限的工具集权限。 它在独立的 Child Session 中运行,有独立的步数上限(steps)和消息上下文, 执行完毕后将结果以 tool_result 形式返回给 Primary Agent。

1.2 Primary Agent vs Sub Agent

维度Primary Agent(如 Build/Plan)Sub Agent(如 Explore/General)
交互方式 用户直接对话,Tab 切换 通过 task 工具或 @mention 间接调用
ReAct 循环 主循环(由 prompt.ts:runLoop() 驱动) 独立子循环,结果序列化返回
会话上下文 主 Session(包含完整对话历史) 子 Session(只包含本次任务上下文),执行结束即序列化
工具集 全部工具(bash, edit, read, grep, task, ...) 按权限过滤(如 Explore 只有 read/grep/glob)
TODO 管理 有 todowrite 默认禁用(General 无 todo)
嵌套深度 受 subagent_depth 配置控制(默认 1) 作为子节点,subagent 不会自动调用别的 subagent(可配置开启)
System Prompt 模型专属 + 环境信息 + AGENTS.md + skills + tools Agent 专属 Prompt(替换模型专属 Prompt)

2. 行为分析(做什么)

以下从行为视角分析 Sub Agent 的功能边界与委托执行流程。

2.1 用例图 — Sub Agent 的使用场景全景

展示 Sub Agent 的两类调用者(Primary Agent / 用户)与其可委托的任务类型。

PlantUML diagram
图 1:Sub Agent 顶层用例图

2.2 活动图 — Sub Agent 委托执行流程

展示从 Primary Agent 决策委托到 Sub Agent 完成返回的完整活动链,覆盖权限门控和深度检查。

PlantUML diagram
图 2:Sub Agent 委托执行活动图(带泳道)

2.3 序列图 — Task Tool 调度 Sub Agent 完整序列

以 Build Agent 委托 Explore Agent 搜索 API 端点为例,展示从 task 工具调用到子会话创建、独立 ReAct 循环执行、结果序列化返回的全链路消息流。

PlantUML diagram
图 3:Task Tool → Sub Agent 完整调用序列图(Explore Agent 示例)

序列图关键节点解读

#节点说明
1 task 工具调用 Primary Agent 的 LLM 输出 tool_call: task(subagent_type, prompt, description)。description 必须 3-5 词,prompt 是给 Sub Agent 的具体任务指令。
2 permission.task 检查 支持 glob 模式匹配 —— 例如 "task": {"*": "deny", "explore": "allow"} 只放行 explore,屏蔽其他 Sub Agent。
3 subagent_depth 门控 默认 depth=1:Primary→Sub 是允许的,但 Sub 不能再调 Sub。depth=2 允许 Sub 调 Sub 形成链式委托。
4 Sub Agent 启动 加载 Agent 专属 System Prompt(如 explore.txt),不继承 Primary Agent 的模型专属 Prompt(如 default.txt)。工具集按 Agent 权限过滤。
5 独立 ReAct 循环 Sub Agent 在自己的子 Session 中执行完整的推理→工具调用→结果观察循环,有独立步数上限(steps)。
6 结果序列化返回 Sub Agent 结束后的全部输出文本被打包为 tool_result,追加到主 Session 的 messages 中。Primary Agent 收到指令 "Summarize the task tool output above and continue..."(prompt.ts:446)。
重要区别:Sub Agent 的 System Prompt 替换而非拼接 Primary Agent 的模型专属 Prompt。这意味着 Sub Agent 不会看到 Primary Agent 的行为指令(如 beast.txt 的 "keep going until resolved"),而是严格按自身 Prompt 行事。

3. 结构分析(由什么组成)

3.1 组件图 — Sub Agent 调度架构

展示 Sub Agent 调度系统的分层组件架构:Primary Agent → Task Tool Dispatcher(权限门控 + 深度门控)→ Sub Agent Registry → Sub Agent Runtime(Session Manager + ReAct Loop + System Prompt Loader)→ 过滤后的工具层。

PlantUML diagram
图 4:Sub Agent 调度系统组件架构图

4. 内置 Sub Agent 详解

OpenCode 提供 3 个内置 Sub Agent,源码位于 packages/core/src/plugin/agent.ts 和 packages/opencode/src/agent/prompt/*.txt。

4.1 General

属性值
用途复杂搜索、多步任务、并行工作
工具全工具(bash, edit, read, grep, glob, webfetch, task, skill, question)
TODO无 todowrite(区分于 Primary Agent)
文件写入可写(有 edit)
典型 Prompt"General-purpose agent for researching complex questions and executing multi-step tasks."
使用场景:当 Primary Agent 需要搜索多个代码库、对比分析、或执行需要多步骤的外部研究时,委派给 General。General 可同时启动多个并行实例(Launch multiple agents concurrently)。

4.2 Explore

属性值
用途快速文件搜索、关键词定位、代码库理解
工具只读 — read, grep, glob
文件写入不可
速度"Fast agent" — 设计用于快速扫描
典型 Prompt"You are a file search specialist. You excel at thoroughly navigating and exploring codebases."
使用场景:当需要快速定位文件、搜索类定义、查找 API 端点等只读探索任务时使用。因为是只读的,适合在不确定任务范围时先用 Explore 做初步探索。

4.3 Scout

属性值
用途外部依赖研究、库源码检查、对照上游实现
工具只读 — read, grep, glob(可在托管缓存目录中操作)
特殊性可以克隆依赖仓库到 OpenCode 托管缓存目录(tmp/opencode)
典型 Prompt只读,用于外部依赖研究
使用场景:当项目依赖某个 npm/pip 包,需要查看其源码来理解行为、排查 bug 或对照实现时使用。Scout 会克隆到 OpenCode 的托管缓存目录而非污染工作区。

5. Task Tool — Sub Agent 的调度入口

task 工具是 Primary Agent 与 Sub Agent 之间的唯一接口。 Primary Agent 的 LLM 产出 tool_call: task(...),由 Runtime 层解析、 创建子会话、注入 Sub Agent Prompt、启动独立 ReAct 循环、最终将结果序列化返回。

5.1 参数 Schema

参数类型必填说明
descriptionstring是任务简述(3-5 词),用于日志/UI 显示
promptstring是给 Sub Agent 的完整任务指令(高度详细的自然语言指令)
subagent_typestring是要调用的 Sub Agent 类型名称(如 "explore"、"general"、"scout" 或自定义名称)
task_idstring否续跑已有任务(复用之前创建的 Sub Agent 会话上下文)
commandstring否触发该 task 的命令(用于日志追溯)

5.2 调度流程

核心调度路径(prompt.ts / task.ts):

LLM 产出 task tool_call → Permission.check("task", subagent_type) → SessionManager.createChild() 检查 subagent_depth → 加载 Sub Agent System Prompt + 过滤工具集 → 新 ReAct 循环 runLoop() → 结果序列化 → tool_result → 追加到主 Session messages → 注入续跑提示 "Summarize the task tool output and continue"

6. 自定义 Sub Agent

6.1 JSON 配置方式

{
  "agent": {
    "code-reviewer": {
      "description": "Reviews code for best practices and potential issues",
      "mode": "subagent",
      "model": "anthropic/claude-sonnet-4-5",
      "temperature": 0.1,
      "steps": 10,
      "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
      "permission": {
        "edit": "deny",
        "bash": "deny"
      }
    }
  }
}

6.2 Markdown 配置方式

放在 ~/.config/opencode/agents/(全局)或 .opencode/agents/(项目级):

---
description: Writes and maintains project documentation
mode: subagent
permission:
  bash: deny
steps: 8
---
You are a technical writer. Create clear, comprehensive documentation.
Focus on:
- Clear explanations
- Proper structure
- Code examples
- User-friendly language

6.3 配置选项全览

选项类型说明
descriptionstring必填。Agent 用途描述,帮助 LLM 决定何时调用
mode"primary" | "subagent" | "all"设置为 "subagent" 即声明为子代理。默认 "all"
modelstring指定模型(如 "anthropic/claude-haiku-4-5")。不指定则继承 Primary Agent 的当前模型
temperaturefloat (0.0-1.0)控制随机性:0.0-0.2 确定性(评审/分析),0.6+ 创造性(头脑风暴)
top_pfloat (0.0-1.0)核采样参数,替代 temperature 控制多样性
stepsint最大迭代步数。不设则无限循环至 LLM 主动停止
promptstring自定义 System Prompt(替代 Agent 默认 Prompt)。支持 "{file:./path.txt}" 引用外部文件
permissionobject工具权限(allow/ask/deny)。参见 8.3 权限速查
hiddenbool设为 true 则在 @ 自动补全菜单中隐藏,仅能通过 task 工具程序化调用
disablebool设为 true 禁用此 Agent
colorhex | theme keywordUI 显示颜色(如 "#ff6b6b")
Sub Agent 模型继承规则:若不指定 model,Sub Agent 使用调用它的 Primary Agent 的当前模型。这确保模型一致性,也可通过显式指定更快的模型(如 haiku)来降低成本和延迟。

7. Sub Agent System Prompt

Sub Agent 启动时用自己的专属 System Prompt替换 Primary Agent 的模型专属 Prompt。位于 packages/opencode/src/agent/prompt/*.txt。

Agent文件System Prompt 首句关键约束
General agent.ts 常量 "General-purpose agent for researching complex questions and executing multi-step tasks." 无 todowrite,可并行启动多个实例
Explore explore.txt "You are a file search specialist. You excel at thoroughly navigating and exploring codebases." 只读(read/grep/glob),不可修改文件
Scout scout.txt 只读,用于外部依赖研究 可在 tmp/opencode 托管缓存中克隆依赖仓库
Compaction compaction.txt "You are an anchored context summarization assistant for coding sessions." mode: primary 但隐藏,系统自动触发;只总结不回答对话
Title title.txt "You are a title generator. You output ONLY a thread title." ≤50 字符单行
Summary summary.txt "Summarize what was done in this conversation." 2-3 句,第一人称
Generate generate.txt "You are an elite AI agent architect specializing in crafting high-performance agent configurations." 输出 JSON schema
Prompt 替换(非拼接):Sub Agent 的 System Prompt 完全替换 Primary Agent 的模型专属 Prompt(如 default.txt、anthropic.txt)。但环境信息(model、workspace、git status、date)和 AGENTS.md 指令仍会拼接。

深层含义:这意味着如果默认 Primary Agent 的 Prompt 中有 "keep going until resolved" 等指令,Sub Agent 看不到这些——它完全按自己 Prompt 中的指令行事。这是有意为之:Sub Agent 的范围应当由 Primary Agent 给定的 prompt 参数精确控制。

8. 实战速查手册

8.1 配置键速查

配置键位置说明
agent.<name>.modeopencode.json / agents/*.md设为 "subagent" 声明为子代理
agent.<name>.descriptionopencode.json / agents/*.md必填,决定 LLM 何时调度它
agent.<name>.modelopencode.json / agents/*.md不填则继承 Primary Agent 的模型
agent.<name>.stepsopencode.json / agents/*.md最大步数(默认 Infinity)
agent.<name>.temperatureopencode.json / agents/*.md0.0-1.0,不填则用模型默认值
agent.<name>.hiddenopencode.json / agents/*.mdtrue 则在 @ 菜单中隐藏
agent.<name>.disableopencode.json / agents/*.mdtrue 则禁用
agent.<name>.permissionopencode.json / agents/*.md工具权限控制
agent.<name>.permission.taskopencode.json / agents/*.md控制该 Agent 可调度哪些 Sub Agent(glob 匹配)
subagent_depthopencode.json(全局)Sub Agent 嵌套深度(默认 1)

8.2 调用流程速查

方式语法适用场景
自动委托LLM 自行决定调用 task 工具Primary Agent 判断任务适合委托时自动触发
@-mention 手动调用@explore 搜索所有 API 端点用户主动要求用特定 Sub Agent
并行调用Primary Agent 同时发出多个 task tool_call需要并行搜索/分析时
续跑已有任务task_id 参数复用之前会话分阶段执行同一任务

8.3 权限速查

权限键值行为
task"allow"允许调用所有 Sub Agent
task"ask"每次调用 Sub Agent 都弹审批
task"deny"禁止调用任何 Sub Agent
task{"*": "deny", "explore": "allow"}只允许 explore,其他 Sub Agent 被 deny 时从 task 工具描述中移除
task{"orchestrator-*": "allow"}glob 模式:允许所有 orchestrator- 前缀的 Agent
注意:即使 permission.task 设为 deny,用户仍可通过 @-mention 手动调用 Sub Agent。权限只约束 Primary Agent 通过 task 工具的自动调度。

9. 源码分析 — 关键实现路径

以下基于 packages/opencode/src/tool/task.ts 和 task.txt 源码,厘清 Sub Agent 的创建、调度与并发模型。

9.1 Child Session 创建

Sub Agent 的底层实体是 child Session,而非操作系统线程。 调用 task 工具时,task.ts:142-158 走 sessions.create({ parentID, ... }) 创建一条子会话记录, 随后通过 BackgroundJob.start()(task.ts:259)将任务以 Effect Fiber(协程)形式调度执行。

步骤源码位置行为
1. 权限检查 task.ts:104-114 调用 ctx.ask({ permission: "task", patterns: [subagent_type] }),走 permission.task 规则(glob 匹配)
2. 解析 Agent task.ts:116-119 agent.get(params.subagent_type) 解析目标 Sub Agent 的 prompt / model / tools
3. task_id 续跑或新建 task.ts:121-158 若传 task_id 则复用已有会话;否则 sessions.create({ parentID, ... }) 新建 child Session
4. 权限合并 task.ts:125-157 deriveSubagentSessionPermission() 合并父 deny + 子 restricts,默认添加 todowrite:deny 和 task:deny
5. 模型继承 task.ts:167-170 Sub Agent 若未单独指定 model,则继承 Primary Agent 当前会话的 providerID 和 modelID
6. 执行调度 task.ts:242-272 先尝试 background.extend()(并发扩展已有 job),否则 background.start() 新建后台 job
7. 前台/后台模式 task.ts:291-333 background:true 走异步模式立即返回;默认前景模式用 Effect.raceFirst 阻塞等待结果
Child Session 的生命周期: sessions.create()(session.ts:669)写一条 parentID 非空的 session 记录 → ops.prompt()(task.ts:188)以该 session 为目标执行 ReAct 循环 → 结果序列化为 <task id="..." state="completed"> XML 注入父会话(task.ts:64-79)→ sessions.remove()(session.ts:608)删父会话时递归删除子会话。

9.2 并发与重入

task.txt:13 明确指示:

Launch multiple agents concurrently whenever possible, to do that, use a single message with multiple tool uses.

结合源码得到以下结论:

问题答案源码依据
指派 Sub Agent = 创建线程? 否。是创建 child Session + Effect Fiber(协程),运行在 Node.js 事件循环上,非 OS 线程。 task.ts:142-158(sessions.create)+ task.ts:259(background.start)
同一 Sub Agent 可同时重复指派吗? 可以。每次调用不传 task_id 即创建 全新的独立 child Session,互不干扰。 task.ts:121-123(task_id 判断)+ task.ts:142-158(sessions.create)
能否定义一个全能 Sub Agent 并发跑多任务? 可以。设计一个拥有完整工具集的 subagent(如 General),同一消息发出多个 task tool_call,每个实例独立会话。 task.txt:13(concurrent mandate)+ task.ts:242(background.extend 支持并发 job)
后台模式 background: true 异步执行,父 Agent 不阻塞。需要 OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true。 task.ts:97-102
续跑 传 task_id 复用已有 child Session,在上次上下文基础上继续。 task.ts:121-123
并发模型总结:Effect 的 BackgroundJob 底层为 Effect.forkIn(scope)(Fiber)。多个 task tool_call 在同一消息中发出时,每个都走 background.extend() → background.start() 分支,各自获得独立 Fiber 和 child Session。非后台模式下 Primary Agent 通过 Effect.raceFirst(background.wait, background.waitForPromotion)(task.ts:309-312)阻塞等待,因此并发子任务通常结合后台模式使用。

9.3 组件总表

组件路径职责
Task Toolpackages/opencode/src/tool/task.ts调度入口:权限/深度门控 → Session 创建 → BackgroundJob 启动 → 结果回注
Task Tool Promptpackages/opencode/src/tool/task.txtLLM 的工具描述文本(含并发指令)
Session Servicepackages/opencode/src/session/session.tscreate(parentID)、children()、remove() 递归删除
Subagent Permissionspackages/opencode/src/agent/subagent-permissions.tsderiveSubagentSessionPermission():合并父 deny + 子 restricts
Background Job (Core)packages/core/src/background-job.ts核心 job 引擎:start / extend / wait / promote / cancel
Background Job (Wrapper)packages/opencode/src/background/job.ts实例级 BackgroundJob.Service 封装
Agent Registrypackages/opencode/src/agent/agent.ts内置 Sub Agent 定义(General / Explore / Scout)
Agent Config Schemapackages/core/src/config/agent.tsAgent 配置 schema v2(mode: "subagent" 等)
Prompt Filespackages/opencode/src/agent/prompt/*.txt各 Sub Agent 专属 System Prompt
Session Promptpackages/opencode/src/session/prompt.ts处理 @agent mention、subtask 分发、prompt 拼装